package org.example.iot;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioChannelOption;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

public class Test0x2000 {
    public static void main(String[] args) throws InterruptedException {
        NioEventLoopGroup worker = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.channel(NioSocketChannel.class);
        bootstrap.group(worker);
        bootstrap.option(NioChannelOption.TCP_NODELAY, true);
        bootstrap.handler(new ChannelInitializer<NioSocketChannel>() {
            @Override
            protected void initChannel(NioSocketChannel ch) throws Exception {
                ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                    //和服务器建立连接之后的回调
                    @Override
                    public void channelActive(ChannelHandlerContext ctx) throws Exception {
                        System.out.println("连接建立");
                        //执行登录
                        byte[] loginBytes = ByteBufUtil.decodeHexDump("028f525c6500990001014457475a434a59323331313038393939322e30322e30303031015b525c6538363531333730363131313638383934363030383435343337303332383338393836303443353130323232303237333238331f3c1f2c01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009f130d0a");
                        ctx.writeAndFlush(Unpooled.buffer().writeBytes(loginBytes));
                        TimeUnit.SECONDS.sleep(5);


                        /**
                         * 025034dc5f002b000202010101014457475a434a59323331323138313032010101014457475a434a5932333132313831303376b50d0a
                         */
                        //上报传感器信息
                        //头部
                        byte[] bytes1 = ByteBufUtil.decodeHexDump("025034dc5f");

                        ByteBuf byteBuf= ByteBufAllocator.DEFAULT.buffer();
                        byteBuf.writeBytes(bytes1);
                        //数据长度 = 指令码 + 传感器数量 + 传感器信息
                        byteBuf.writeShort(2+1+(20*1));
                        //写入指令码
                        byteBuf.writeBytes(ByteBufUtil.decodeHexDump("0002"));
                        //写入传感器数量
                        byteBuf.writeByte(1);
                        //写入20字节445747
                        byteBuf.writeBytes(ByteBufUtil.decodeHexDump("01010101"));
                        byteBuf.writeBytes("DWGZCJY241111111".getBytes(StandardCharsets.UTF_8));


                        //写入CRE
                        byte[] crcBytes = crc16CCITTFalse(ByteBufUtil.getBytes(byteBuf));
                        byteBuf.writeBytes(crcBytes);
                        //写入尾部
                        byteBuf.writeBytes(ByteBufUtil.decodeHexDump("0d0a"));
                        ctx.writeAndFlush(byteBuf);

                        /**
                         * 上传数据包
                         */
                        byte[] bytes = ByteBufUtil.decodeHexDump("02413D5C65042120000350000018184FF08B010000082080010001DE20C2F4FD20C2C66D21C2FAED20C2B98D21C2CC5D21C2ACAD21C2E71D21C201DE20C2FAED20C2D93D21C2C66D21C2228E20C2E02D21C201DE20C2E71D21C20EBE20C2C66D21C2CC5D21C2B29D21C2D34D21C29FCD21C291ED21C2BF7D21C2B29D21C2D93D21C2713D22C2B29D21C2BF7D21C2567D22C2713D22C2BF7D21C20200E86A4FC2BADA4FC2B3EA4FC2C1CA4FC2A01A50C2933A50C2992A50C2A01A50C2D49A4FC2CEAA4FC2A60A50C2B3EA4FC2E17A4FC2FB3A4FC2022B4FC2CEAA4FC2ADFA4FC2E17A4FC2E17A4FC2ADFA4FC2992A50C2992A50C2DB8A4FC2F54A4FC2E17A4FC2091B4FC2022B4FC2F54A4FC2E17A4FC2022B4FC2B3EA4FC28C4A50C20300FE4392C2FE4392C2F55B92C2DE9392C2DE9392C2D4AB92C2053492C2F85392C2023C92C2EB7392C2E48392C2FE4392C20F1C92C2FB4B92C2E77B92C2F85392C2F16392C2DA9B92C2EE6B92C2150C92C2F55B92C2EE6B92C21CFC91C2E77B92C2E77B92C2121492C20B2492C2023C92C2FE4392C2F16392C2082C92C2E48392C2040053050FC1F0850DC18E060CC125060DC125060DC111C70AC15F070AC111C70AC125060DC1C80709C145470AC1A8C60BC1BC050EC1F0850DC174460CC1DC460BC1DC460BC174460CC12B870AC145470AC1A8C60BC1A8C60BC174460CC10B460DC125060DC188850EC18E060CC13FC60CC13FC60CC159860CC159860CC125060DC105009C333AC11FF438C188F437C14DF33AC1DE713EC182733AC1D0B339C182733AC133333BC1EB7339C182733AC1D0B339C168B33AC1EB7339C17CF23CC11FF438C1D0B339C119733BC1D0B339C1EB7339C1B6F339C14DF33AC182733AC1F1F436C1BC7437C133333BC1FFB23BC1053439C1D0B339C14DF33AC1D0B339C147723DC10600C4B1BEC09031BFC08AB0C1C09031BFC0F2B0C0C01B2FC5C0C4B1BEC09031BFC05530C2C02731C0C01B2FC5C05BB1BFC0B8AFC3C0F2B0C0C05530C2C0E6AEC5C05BB1BFC06132BDC096B2BCC05530C2C0832FC4C096B2BCC021B0C2C03333BBC03333BBC02731C0C08AB0C1C09031BFC09031BFC0BE30C1C02731C0C0F931BEC00700931887C2804887C2C1A886C28A3087C26F7087C2A1F886C2971087C2902087C2A4F086C29D0087C29A0887C2766087C2834087C2B1D086C2971087C28A3087C2AED886C2B8C086C2804887C2971087C2766087C26F7087C2834087C2B4C886C2A1F886C2BEB086C2B1D086C2A1F886C29A0887C2A1F886C2A7E886C2AED886C20800CF660BC2F0160BC20AD70AC20AD70AC23F570AC2F7060BC2C2860BC2A8C60BC2DC460BC2F7060BC294F60BC2B5A60BC2F0160BC2C2860BC2E3360BC2AEB60BC2F7060BC2DC460BC2E9260BC2C9760BC2F7060BC204E70AC2DC460BC2DC460BC287160CC2BC960BC2BC960BC2B5A60BC2B5A60BC2DC460BC28E060CC2C2860BC2310B0D0A");
                        ByteBuf buffer = Unpooled.buffer();
                        buffer.writeBytes(bytes);
                        ctx.writeAndFlush(buffer);

                    }
                });
            }
        });
        ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 9876).sync();
        Channel channel = channelFuture.channel();

    }

    public static byte[] crc16CCITTFalse(byte[] bytes) {
        int crc = 0xffff; // initial value
        int polynomial = 0x1021; // poly value
        for (int index = 0; index < bytes.length; index++) {
            byte b = bytes[index];
            for (int i = 0; i < 8; i++) {
                boolean bit = ((b >> (7 - i) & 1) == 1);
                boolean c15 = ((crc >> 15 & 1) == 1);
                crc <<= 1;
                if (c15 ^ bit){
                    crc ^= polynomial;
                }
            }
        }
        crc &= 0xffff;
        return new byte[] { (byte) ((0xff00 & crc) >> 8),(byte) (0xff & crc)  };
    }
}
